package com.lu.manage.modular.system.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lu.manage.core.common.constant.SystemConstant;
import com.lu.manage.core.common.exception.SysLogExcepetion;
import com.lu.manage.core.common.node.TreeNodes;
import com.lu.manage.core.common.node.ZTreeNode;
import com.lu.manage.core.tips.SuccessTip;
import com.lu.manage.core.utils.ToolUtil;
import com.lu.manage.modular.system.mapper.DictMapper;
import com.lu.manage.modular.system.model.Dict;
import com.lu.manage.modular.system.service.DictService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Project LuBoot
 * @Author: zhanglu
 * @Date: 2019-11-17 00:46:19
 * @Description: 基础字典 服务实现类
 */
@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {

    @Override
    public Object listPage(Map<String, Object> map) throws SysLogExcepetion {
        SuccessTip successTip = new SuccessTip();
        try {
            Page page = new Page(Integer.valueOf((String)map.get(SystemConstant.PAGE)), Integer.valueOf((String)map.get(SystemConstant.LIMIT)));
            QueryWrapper queryWrapper = new QueryWrapper();
            map.forEach((k, v) -> {
                if(!k.equals(SystemConstant.PAGE) && !k.equals(SystemConstant.LIMIT)){
                    if(k.equals(SystemConstant.SEARCH_WORDS)){
                        queryWrapper.like("name", v);
                    }else {
                        queryWrapper.eq(k, v);
                    }
                }
            });
            IPage<Dict> dictList = this.baseMapper.selectPage(page, queryWrapper);
            successTip.setCount(dictList.getTotal());
            successTip.setData(dictList.getRecords());
        } catch (Exception e) {
            throw new SysLogExcepetion(Thread.currentThread(), e);
        }
        return successTip;
    }

    @Override
    public Object list(Map<String, Object> map) throws SysLogExcepetion {
        List<Dict> dictList = new ArrayList<>();
        try {
            QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
            if(ToolUtil.isNotEmpty(map)){
                map.forEach((k, v) -> {
                    queryWrapper.eq(k, v);
                });
            }
            dictList = this.baseMapper.selectList(queryWrapper);
        } catch (Exception e) {
            throw new SysLogExcepetion(Thread.currentThread(), e);
        }
        return dictList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Object addObj(Dict dict) throws SysLogExcepetion {
        try {
            //组装属性，设置父级菜单编号
            dict = this.dicSetPid(dict);
            this.save(dict);
            return dict;
        } catch (Exception e) {
            throw new SysLogExcepetion(Thread.currentThread(), e);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Object updateObj(Dict dict) throws SysLogExcepetion {
        try {

            Dict oldDict = this.getById(dict.getId());

            //设置父级菜单编号
            Dict newDict = this.dicSetPid(dict);

            //查找该节点的子集合,并修改相应的pid、pids、level(因为字典修改后,层级可能也变化了)
            updateSubDictLevel(oldDict, newDict);

            this.updateById(dict);
            return dict;
        } catch (Exception e) {
            throw new SysLogExcepetion(Thread.currentThread(), e);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Object deleteObj(String id) throws SysLogExcepetion {
        try {
            if(ToolUtil.isEmpty(id)){
               throw new Exception("删除异常，id不能为空");
            }
            //删除当前菜单
            this.removeById(id);

            //删除当前菜单下的所有子菜单
            List<Dict> dicts = this.baseMapper.getDictsLikePids(id);

            for (Dict dict : dicts) {
                this.removeById(dict.getId());
            }
            return new SuccessTip();
        } catch (Exception e) {
            throw new SysLogExcepetion(Thread.currentThread(), e);
        }
    }

    @Override
    public List<ZTreeNode> dictTree() {
        return this.baseMapper.dictTree();
    }

    @Override
    public void updateState(String id, Integer state) {
        Dict dict = new Dict();
        dict.setId(id);
        dict.setState(state);
        this.updateById(dict);
    }

    @Override
    public List<Dict> treeTable(String dictTypeId, String searchWords) throws SysLogExcepetion {
        QueryWrapper queryWrapper = new QueryWrapper();
        if(ToolUtil.isEmpty(dictTypeId)){
            throw new SysLogExcepetion(Thread.currentThread(), "");
        }
        queryWrapper.eq("dict_type_id", dictTypeId);
        if(ToolUtil.isNotEmpty(searchWords)){
            queryWrapper.like("name", searchWords);
            queryWrapper.like("dict_key", searchWords);
        }
        queryWrapper.orderByAsc("level", "sort");
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public void sort(String nodes) throws SysLogExcepetion {
        List<TreeNodes> nodeList = JSONArray.parseArray(nodes, TreeNodes.class);
        for (TreeNodes node : nodeList) {
            handle(0, node);
        }
    }

    /**
     * 转化请求的数据：
     *  - 通过选择的父级id，设置自己的pid、pids、level
     * @param dict
     * @return
     */
    private Dict dicSetPid(Dict dict) {

        if(ToolUtil.isEmpty(dict.getPid()) || dict.getPid().equals(SystemConstant.pid)){
            dict.setPid(SystemConstant.pid);
            dict.setLevel(SystemConstant.pLevels);
            dict.setPids("[" + SystemConstant.pid + "],");
        }else {
            Dict pDict = this.getById(dict.getPid());
            Integer pLevel = pDict.getLevel();
            dict.setPid(pDict.getId());
            dict.setLevel(pLevel + 1);
            dict.setPids(pDict.getPids() + "[" + pDict.getId() + "],");
        }

        return dict;
    }

    /**
     * 更改所有子菜单的结构
     * @param oldDict
     * @param newDict
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateSubDictLevel(Dict oldDict, Dict newDict) {
        List<Dict> dicts = this.baseMapper.getDictsLikePids(oldDict.getId());

        for (Dict dict : dicts) {

            //更新pcodes
            String oldPidsPrefix = oldDict.getPids() + "[" + oldDict.getId() + "],";
            String oldPidsSuffix = dict.getPids().substring(oldPidsPrefix.length());
            String dictPids = newDict.getPids() + "[" + newDict.getId() + "]," + oldPidsSuffix;
            dict.setPids(dictPids);

            //更新levels
            int level = StrUtil.count(dictPids, "[");
            dict.setLevel(level);

            this.updateById(dict);
        }
    }

    public void handle(int index, TreeNodes treeNodes){
        int count = 0;
        for (TreeNodes n : treeNodes.getChildren()) {
            count++;
            if(ToolUtil.isEmpty(n.getChildren())){
                Dict dict = new Dict();
                dict.setId(n.getId());
                dict.setSort(count);
                this.baseMapper.updateById(dict);
            }else {
                index++;
                handle(index, n);
                Dict dict = new Dict();
                dict.setId(n.getId());
                dict.setSort(index);
                this.baseMapper.updateById(dict);
            }
        }
    }

}
